package com.google.api.adwords.starterkit.Synchronizer;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;

import com.google.api.adwords.starterkit.db.structures.GeoTargetStructure;
import com.google.api.adwords.starterkit.settings.StarterKitSettings;
import com.google.api.adwords.starterkit.utils.DumpExceptions;
import com.google.api.adwords.v201101.cm.CampaignTargetOperation;
import com.google.api.adwords.v201101.cm.CityTarget;
import com.google.api.adwords.v201101.cm.CountryTarget;
import com.google.api.adwords.v201101.cm.GeoTarget;
import com.google.api.adwords.v201101.cm.GeoTargetList;
import com.google.api.adwords.v201101.cm.Operator;
import com.google.api.adwords.v201101.cm.ProvinceTarget;

/**
 * The Class GeoTargetSynchronizer is responsible to keep all GeoTarget 
 * information from AdWords system synchronized with local DB.
 * 
 * @author rodrigo.f.vale@gmail.com (Rodrigo Vale)
 */
public class GeoTargetSynchronizer extends TargetsSynchronizer {
  
  public GeoTargetSynchronizer(StarterKitSettings starterKitSetting, 
      Connection conn) {
    super(starterKitSetting, conn);  
  }

  /**
   * Process the updates at geoTarget table.
   */
  protected void put() {
    log.debug("Preparing GeoTarget to be sent to AdWords");
    geoTargetTable.updateCampaignsIds();
  
    ResultSet rs = geoTargetTable.getModified();
    try {
      HashSet<CampaignTargetOperation> campaignTargetOperation 
          = new HashSet<CampaignTargetOperation>();
      HashSet<GeoTarget> geoTarget = new HashSet<GeoTarget>();
      long lastCampaignId = 0;
      long campaignId = 0;
      while (rs.next()) {
        campaignId = rs.getLong("CampaignId");
        GeoTargetStructure geoTargetStructure = new GeoTargetStructure(
            0,
            campaignId, 
            rs.getString("City"),
            rs.getString("Province"),
            rs.getString("Country"),
            rs.getBoolean("Exclude"));
        if (lastCampaignId != campaignId) {
          if (geoTarget.size() > 0) {
            GeoTargetList geoTargetList = new GeoTargetList();
            geoTargetList.setCampaignId(lastCampaignId);
            geoTargetList.setTargets(geoTarget.toArray(new GeoTarget[geoTarget
                .size()]));
  
            CampaignTargetOperation geoTargetOperation 
                = new CampaignTargetOperation();
            geoTargetOperation.setOperand(geoTargetList);
            geoTargetOperation.setOperator(Operator.SET);
            campaignTargetOperation.add(geoTargetOperation);
          }
          lastCampaignId = campaignId;
          geoTarget.clear();
        }
        if (geoTargetStructure.getCityName().equals("")
            && geoTargetStructure.getProvinceCode().equals("")
            && !geoTargetStructure.getCountryCode().equals("")) {
          geoTarget.add(new CountryTarget(null,
              geoTargetStructure.getExclude(), geoTargetStructure
                  .getCountryCode()));
        } else if (geoTargetStructure.getCityName().equals("")
            && !geoTargetStructure.getProvinceCode().equals("")) {
          geoTarget.add(new ProvinceTarget(null, geoTargetStructure
              .getExclude(), geoTargetStructure.getProvinceCode()));
        } else if (!geoTargetStructure.getCityName().equals("")) {
          geoTarget.add(new CityTarget(null, geoTargetStructure.getExclude(),
              geoTargetStructure.getCityName(), geoTargetStructure
                  .getProvinceCode(), geoTargetStructure.getCountryCode()));
        }
      }
      rs.close();
  
      if (geoTarget.size() > 0) {
        GeoTargetList geoTargetList = new GeoTargetList();
        geoTargetList.setCampaignId(lastCampaignId);
        geoTargetList.setTargets(geoTarget.toArray(new GeoTarget[geoTarget
            .size()]));
  
        CampaignTargetOperation networkTargetOperation 
            = new CampaignTargetOperation();
        networkTargetOperation.setOperand(geoTargetList);
        networkTargetOperation.setOperator(Operator.SET);
        campaignTargetOperation.add(networkTargetOperation);
      }
      processOperations(campaignTargetOperation);
    } catch (SQLException e) {
      DumpExceptions.dumpSQLException(e);
    }
    campaignTable.resetGeoTargetFlags();    
  }
}
